<script setup lang="ts">
import { useEffect } from "@/framework/vue/hooks";
import { ref, shallowRef } from "vue";

/* 元素可见性监听 */

defineOptions({ name: "visible-observer" });

const { defaultVisible } = defineProps<{
  /** 默认可见*/
  defaultVisible?: boolean;
}>();
const emits = defineEmits<{
  (e: "visible-change", visible: boolean): void;
}>();

const element = shallowRef<HTMLDivElement>();
const visible = ref(defaultVisible ?? false);

const setVisible = (v: boolean) => {
  if (v === visible.value) return;
  visible.value = v;
  emits("visible-change", v);
};

useEffect(() => {
  const el = element.value;
  if (!el) return;

  const rect = el.getBoundingClientRect();
  setVisible(rect.width > 0 && rect.height > 0);

  const observer = new IntersectionObserver(entries => {
    const entry = entries[entries.length - 1];
    setVisible(entry.isIntersecting);
  });
  observer.observe(el);
  return () => {
    observer.unobserve(el);
    observer.disconnect();
  };
});
</script>

<template>
  <div ref="element" class="visible-observer">
    <slot :visible="visible" />
  </div>
</template>

<style lang="less">
.visible-observer {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
}
</style>
